package org.jeecg.modules.miniAppCustomerEndPoint.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.miniAppCustomerEndPoint.constant.JxCustomerConstant;
import org.jeecg.modules.miniAppCustomerEndPoint.entity.JxOrderDetailDo;
import org.jeecg.modules.miniAppCustomerEndPoint.entity.JxOrderDo;
import org.jeecg.modules.miniAppCustomerEndPoint.entity.JxShoppingCartFoodDo;
import org.jeecg.modules.miniAppCustomerEndPoint.enums.JxOrderStateEnum;
import org.jeecg.modules.miniAppCustomerEndPoint.enums.JxPaymentMethodEnum;
import org.jeecg.modules.miniAppCustomerEndPoint.mapper.JxOrderDetailMapper;
import org.jeecg.modules.miniAppCustomerEndPoint.mapper.JxOrderMapper;
import org.jeecg.modules.miniAppCustomerEndPoint.mapper.JxShoppingCartMapper;
import org.jeecg.modules.miniAppCustomerEndPoint.utils.JxUserUtil;
import org.jeecg.modules.platformMasterEndPoint.utils.JxOrderUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;

@Service
@Slf4j
public class JxOrderServiceImpl {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private JxOrderMapper jxOrderMapper;

    @Autowired
    private JxOrderDetailMapper jxOrderDetailMapper;

    @Autowired
    private JxShoppingCartMapper jxShoppingCartMapper;

    /**
     * todo 待实现，用户下单时，对订单做如下校验
     * (1) 涉及规格的菜品，比如 自选套餐，选择不同规格时，价格是否计算正确
     * (2) 优惠券是否使用正确，比如 “限定时间下单才能使用的优惠券”，是否可以使用，是否能够享受优惠
     */
    public void checkOrderPrice() {

    }

    /**
     * 对用户选购的菜品是否有库存进行校验，若没有库存则将 菜品id 添加到 列表中
     * @param outStockFoods 没有库存的菜品id列表
     * @param shoppingCartId 用户购物车中的购物项id
     * @return
     */
    public void checkFoodStock(List<JSONObject> outStockFoods, String siteId, String shoppingCartId) {
        JxShoppingCartFoodDo shoppingCartFoodDo = jxShoppingCartMapper.selectById(shoppingCartId);
        String storeId = shoppingCartFoodDo.getStoreId();
        // key字符串格式为：stock_站点id_店铺id
        String storeFoodStockKey = "stock_" + siteId +"_" + storeId;
        String foodId = shoppingCartFoodDo.getFoodId();
        int oldStock = (int)redisUtil.hget(storeFoodStockKey, foodId);
        int remainingFoodCount = (int)redisUtil.hincr(storeFoodStockKey, foodId, -1);
        int newStock = (int)redisUtil.hget(storeFoodStockKey, foodId);
        log.warn("key: {}, old: {}, new: {}, return: {}", storeFoodStockKey, oldStock, newStock, remainingFoodCount);
        if (remainingFoodCount < 0) {
            // 该菜品已经没有库存了，需要向小程序端返回 库存不足信息
            JSONObject outStockInfo = new JSONObject();
            outStockInfo.put("shoppingCartId", shoppingCartId);
            outStockInfo.put("foodId", foodId);
            outStockFoods.add(outStockInfo);
        }
    }

    /**
     * 根据用户最终支付的金额，计算本次订单对应的积分金额，当前兑换规则较为简单，1元对应1个积分
     * @param orderPrice
     * @return
     */
    public Integer calcOrderIntegral(Integer orderPrice) {

        return orderPrice / 100;
    }

    /**
     * 向 jx_order 和 jx_order_detail 表中添加记录
     * @param requestBody
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String insertOrderRecords(String userId, JSONObject requestBody) {

        String siteId = requestBody.getString("siteId");
        Integer totalPrice = requestBody.getInteger("totalPrice");
        String couponIds = requestBody.getString("couponIds");
        String note = requestBody.getString("note");
        JxOrderDo jxOrderDo = new JxOrderDo();
        jxOrderDo.setUserId(userId);
        jxOrderDo.setSiteId(siteId);
        jxOrderDo.setPaymentMethod(JxPaymentMethodEnum.WXPAY);
        jxOrderDo.setPaymentId("unpay");
        jxOrderDo.setPayTime(null); // 此时还未支付
        jxOrderDo.setTotalPrice(totalPrice);
        jxOrderDo.setCouponIds(couponIds);
        Integer integral = calcOrderIntegral(totalPrice);
        jxOrderDo.setIntegral(integral); // 此订单产生的积分
        jxOrderDo.setRefundId(null); // 如果申请退货，在微信支付平台对应的 退款id
        jxOrderDo.setState(JxOrderStateEnum.TOPAY); // 待支付
        jxOrderDo.setObjectJson(null);
        jxOrderDo.setDateFlag(JxOrderUtil.todayFlagForIndex()); // 订单所属日期 标致
        jxOrderDo.setCreateTime(new Date());
        // 向 jx_order 表中添加一条记录
        jxOrderMapper.insert(jxOrderDo);

        // 为订单中的每个菜品，在 jx_order_detail 表中添加对应的记录
        JSONArray shoppingCartIds = requestBody.getJSONArray("shoppingCartIds");
        for (int i = 0 ; i < shoppingCartIds.size(); i ++) {
            String shoppingCartId = shoppingCartIds.getString(i);

            JxOrderDetailDo jxOrderDetailDo = new JxOrderDetailDo();
            jxOrderDetailDo.setOrderId(jxOrderDo.getId());
            jxOrderDetailDo.setSiteId(siteId);
            jxOrderDetailDo.setUserId(userId);
            String nameTakingMeal = requestBody.getString("nameTakingMeal");
            String phoneTakingMeal = requestBody.getString("phoneTakingMeal");
            String address = requestBody.getString("address");
            jxOrderDetailDo.setNameTakingMeal(nameTakingMeal);
            jxOrderDetailDo.setPhoneTakingMeal(phoneTakingMeal);
            jxOrderDetailDo.setPickingAddress(address);

            JxShoppingCartFoodDo jxShoppingCartFoodDo = jxShoppingCartMapper.selectById(shoppingCartId);
            String storeId = jxShoppingCartFoodDo.getStoreId();
            String foodId = jxShoppingCartFoodDo.getFoodId();
            Integer count = jxShoppingCartFoodDo.getCount();
            JSONArray specifications = JSONArray.parseArray(jxShoppingCartFoodDo.getSpecification());
            // oneFoodSalePrice 如果是一份菜品，则为该菜品的销售单价，若用户订购了多份同样菜品，则为 多份菜品的总销售价 = 菜品单价 * 菜品份数
            Integer oneFoodSalePrice = jxShoppingCartFoodDo.getSalePrice();
            jxOrderDetailDo.setStoreId(storeId);
            jxOrderDetailDo.setFoodId(foodId);
            jxOrderDetailDo.setFoodPrintName(jxShoppingCartFoodDo.getFoodPrintName());
            jxOrderDetailDo.setSalePrice(oneFoodSalePrice);
            jxOrderDetailDo.setCount(count);
            jxOrderDetailDo.setSpecification(specifications.toJSONString());
            jxOrderDetailDo.setNote(note); // 用户填写的备注
            jxOrderDetailDo.setState(JxOrderStateEnum.TOPAY); // 此时还未支付，订单状态还是 待支付
            Integer pickUpCode = Long.valueOf(redisUtil.incr(JxCustomerConstant.JX_ORDER_PICKUP_CODE, 1)).intValue();
            jxOrderDetailDo.setPickupCode(pickUpCode);
            jxOrderDetailDo.setDateFlag(JxOrderUtil.todayFlagForIndex());
            jxOrderDetailDo.setCreateTime(new Date());
            // 为订单中的每个菜品，向 jx_order_detail 表中添加一条记录
            jxOrderDetailMapper.insert(jxOrderDetailDo);
        }

        return jxOrderDo.getId();
    }

    /**
     * 当用户支付完成后，将 jx_order 和 jx_order_detail 表中的订单状态都更新成 toSend
     * @param orderId
     * @param orderStateEnum
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderState(String orderId, JxOrderStateEnum orderStateEnum) {
        JxOrderDo jxOrderDo = new JxOrderDo();
        jxOrderDo.setState(orderStateEnum); // 支付 成功后，订单状态变更为 toSend，待发货
        jxOrderMapper.update(jxOrderDo, new LambdaUpdateWrapper<JxOrderDo>().eq(JxOrderDo::getId, orderId));

        JxOrderDetailDo jxOrderDetailDo = new JxOrderDetailDo();
        jxOrderDetailDo.setState(orderStateEnum); // 支付 成功后，将 jx_order_detail表中的订单状态变更为 toSend，待发货
        jxOrderDetailMapper.update(jxOrderDetailDo, new LambdaUpdateWrapper<JxOrderDetailDo>().eq(JxOrderDetailDo::getOrderId, orderId));
    }


    public JSONObject queryOrderSummary(String userId) {

        // select state,count(*) from jx_order where user_id = #{userId}  group by state;
        List<HashMap<String, Object>> result =  jxOrderMapper.queryOrderSummary(userId);
        JSONObject formatedResult = new JSONObject();
        if (result != null && result.size() > 0) {

            int total = 0;

            for(int i = 0 ; i < result.size() ; i ++) {
                HashMap<String, Object> item = result.get(i);
                String state = (String)item.get("state");
                long count = (long)item.get("count");

                total += count;
                formatedResult.put(state,count );
            }
            formatedResult.put("total", total);
        } else {
            log.error("无法查询到用户: {} 的订单", userId);
        }

        return formatedResult;
    }


    /**
     *
     * @param orderCode
     * @return
     */
    public String mapOrderTypeCode2String(Integer orderCode) {

        String typeString = "all";
        switch(orderCode) {
            case 1:
                typeString = "toPay";
                break;
            case 2:
                typeString ="toSend";
                break;
            case 3:
                typeString ="toReceive";
                break;
            case 4:
                typeString ="toReview";
        }
        return typeString;
    }

    /**
     * 将规格中的各个菜品项进行拼接，对于自选快餐，最终打印在标签纸上的菜品名是 各个规格项拼接的结果，而非该自旋快餐 菜品名的 名称
     * @param specification
     * @return
     */
    public String buildFoodPrintNameFromSpecification(JSONArray specification) {

        List<String> itemNames = new ArrayList<>();
        for (int k = 0 ; k < specification.size(); k ++) {
            JSONObject specificationItem = specification.getJSONObject(k);
            itemNames.add(specificationItem.getString("name"));
        }
        String printFoodName = String.join("+", itemNames);

        return printFoodName;
    }

    /**
     * 当用户点击下单，并且在 微信支付平台 生成 预支付交易id成功后，将购物车中的商品信息标记删除；如果用户 终止支付，则用户再次打开购物车也看不到商品，必须重新选择
     * @param shoppingCartIds
     * @return
     */
    public Integer deleteShoppingCartItemsByFlag(String orderId, JSONArray shoppingCartIds) {

        List<String> formatedIds = shoppingCartIds.toJavaList(String.class);
        JxShoppingCartFoodDo jxShoppingCartFoodDo = new JxShoppingCartFoodDo();
        jxShoppingCartFoodDo.setOrderId(orderId);
        jxShoppingCartFoodDo.setDelFlag((byte)1);
        Integer updatedCount = jxShoppingCartMapper.update(jxShoppingCartFoodDo, new UpdateWrapper<JxShoppingCartFoodDo>().in("id", formatedIds));
        log.info("下单成功，将购物车中的购物项状态设置为已删除，并回填订单id: {}", orderId);

        return updatedCount;
    }


    /**
     * 根据订单的创建时间，计算出订单可以取消的时间，返回的时间格式为  yyyy-MM-dd HH:mm:ss
     * @param createTime
     * @param storeSupplyTimeSpan
     * @return
     */
    public String calcOrderCanCancelTime(Date createTime, String storeSupplyTimeSpan) {

        JSONObject supplyTimeSpan = JSONObject.parseObject(storeSupplyTimeSpan);
        String createTimeStr = JxUserUtil.formateHHMMSS(createTime);

        String beginTime = supplyTimeSpan.getString("beginTime");
        String endTime = supplyTimeSpan.getString("endTime");
        Date supplyEndTime = JxUserUtil.parseDateFromHHMMSS(endTime);
        Calendar supplyEndTimeCal = Calendar.getInstance();
        supplyEndTimeCal.setTime(supplyEndTime);

        Calendar canCancelTimeCal = Calendar.getInstance();
        canCancelTimeCal.setTime(createTime);
        canCancelTimeCal.set(Calendar.HOUR_OF_DAY, supplyEndTimeCal.get(Calendar.HOUR_OF_DAY));
        canCancelTimeCal.set(Calendar.MINUTE, supplyEndTimeCal.get(Calendar.MINUTE));
        canCancelTimeCal.set(Calendar.SECOND, supplyEndTimeCal.get(Calendar.SECOND));

        if (createTimeStr.compareTo(beginTime) > 0) {
            // 供餐开始时间是前一天晚上19:00， 因此，若按照字典序比较，若下单时间 大于 开始供餐时间，则下单时间一定在前一天晚上，因此，可以取消订单的时间，日期需要加1天
            canCancelTimeCal.add(Calendar.DAY_OF_MONTH, 1);
        }

        return JxUserUtil.formateDateTimeYYYYMMDDHHMMSS(canCancelTimeCal.getTime()) ;
    }

}
